package com.example.springbootflowabledemo.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.example.springbootflowabledemo.constant.ErrorCode;
import com.example.springbootflowabledemo.domian.pojo.sys.SysUser;
import com.example.springbootflowabledemo.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt的工具类
 */
@Slf4j
public class JwtUtil {
    /**
     * 过期时间为7天
     */
    private static final long EXPIRE_TIME = 7 * 24 * 60 * 60 * 1000;

    /**
     * token私钥
     */
    private static final String TOKEN_SECRET = "e7e99385-719b-418c-832d-eb0d59bcd069";

    /**
     * 生成jwt签名
     *
     * @param userId   id
     * @param username 账户
     * @return
     */
    public static String sign(String username, Long userId) {
        //过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        //私钥及加密算法
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        //设置头信息
        HashMap<String, Object> header = new HashMap<>(2);
        header.put("typ", "JWT");
        header.put("alg", "HS256");
        //生成签名
        return JWT.create().withHeader(header).withClaim("username", username).withClaim("userId", userId).withExpiresAt(date).sign(algorithm);
    }


    /**
     * 验证token的真实性
     *
     * @param token token
     * @return
     */
    public static SysUser verity(String token) {
        if (StringUtils.isBlank(token)) {
            throw new ServiceException(ErrorCode.TOKEN_ERROR_CODE, "token不能为空!!!");
        }
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            String trimToken = StringUtils.trim(token);
            if (trimToken.equals(jwt.getToken())) {
                Map<String, Claim> claims = jwt.getClaims();
                Claim userId = claims.get("userId");
                Claim username = claims.get("username");
                SysUser user = new SysUser();
                user.setId(userId.asLong());
                user.setUsername(username.asString());
                return user;
            }
            return null;
        } catch (IllegalArgumentException e) {
            throw new ServiceException(e.getMessage());
        } catch (JWTVerificationException e) {
            log.error("token校验失败", e);
            if (e.getMessage().contains("expired")) {
                throw new ServiceException(ErrorCode.TOKEN_ERROR_CODE, "token已过期!");
            }
            throw new ServiceException(ErrorCode.TOKEN_ERROR_CODE, "无效的token!");
        }
    }


}
